#include "AtConfig.h"

AtConfig::AtConfig()
{

}

void AtConfig::setup() {
  EEPROM.begin(1024); //开启EEPROM，开辟1024个位空间  
}

void AtConfig::waitAtCommand() {
  int second = 3;
  int cnt = 0;
  while (status != ATCONFIG_QUIT)
  {
    waitResponse(500);
    cnt += 1;
    // 1秒
    if (cnt % 2 == 0){
      if (status == ATCONFIG_START) {
        if (second <= 0) {
          // 未进入配置模式，退出
          status = ATCONFIG_QUIT;
        }
        else {
          SerialAT.printf("Wait AT Command %d...\r\n", second);
          second -= 1;
        }
      }
    } 
  }
}

void AtConfig::write(int addr, String value){
  int len = value.length();
  byte high = (len >> 8) & 0xff;
  byte low = len & 0xff;
  EEPROM.write(addr, high);
  EEPROM.write(addr+1, low);
  for (int i = 0; i < len; i++) {
    EEPROM.write(addr + i + 2, value.charAt(i));
  }
  EEPROM.commit();
}

String AtConfig::read(int addr){
  byte high = EEPROM.read(addr);
  byte low = EEPROM.read(addr + 1);
  int len = (high << 8) + low;  
  String value = "";
  for (int i = 0; i < len; i++) {
    char chr = char(EEPROM.read(addr + i + 2));
    value += chr;
  }
  return value;
}


void AtConfig::setConf(String json_str) {
  write(ADDR_BASE_CONF, json_str);
}

String AtConfig::getConf() {
  return read(ADDR_BASE_CONF);
}

void AtConfig::readConf(BaseConf *conf){
  String value = "";
  StaticJsonDocument<1024> doc;
  // read config from eeprom
  value = read(ADDR_BASE_CONF);
  SerialAT.println("eeprome info:");
  SerialAT.println(value);
  DeserializationError error = deserializeJson(doc, value.c_str());
  if (error) {
    SerialAT.print(F("deserializeJson() failed: "));
    SerialAT.println(error.c_str());
    return;
  }
  strlcpy(conf->create_time, doc["create_time"], sizeof(conf->create_time));
  strlcpy(conf->name, doc["name"], sizeof(conf->name));
  strlcpy(conf->version, doc["version"], sizeof(conf->version));
  strlcpy(conf->model, doc["model"], sizeof(conf->model));
  // strlcpy(conf->update_url, doc["update_url"], sizeof(conf->update_url));

  strlcpy(conf->wifi_ssid, doc["wifi_ssid"], sizeof(conf->wifi_ssid));
  strlcpy(conf->wifi_password, doc["wifi_password"], sizeof(conf->wifi_password));

  strlcpy(conf->mqtt_server, doc["mqtt_server"], sizeof(conf->mqtt_server));
  conf->mqtt_port = doc["mqtt_port"];
  strlcpy(conf->mqtt_pub, doc["mqtt_pub"], sizeof(conf->mqtt_pub));
  strlcpy(conf->mqtt_sub, doc["mqtt_sub"], sizeof(conf->mqtt_sub));
  strlcpy(conf->mqtt_sub_sys, doc["mqtt_sub_sys"], sizeof(conf->mqtt_sub_sys));
  strlcpy(conf->mqtt_clientid, doc["mqtt_clientid"], sizeof(conf->mqtt_clientid));
  strlcpy(conf->mqtt_user, doc["mqtt_user"], sizeof(conf->mqtt_user));
  strlcpy(conf->mqtt_password, doc["mqtt_password"], sizeof(conf->mqtt_password));

  SerialAT.println();
  SerialAT.println("[CONFIG]");
  SerialAT.printf("create_time: %s\r\n", conf->create_time);
  SerialAT.printf("name: %s\r\n", conf->name);
  SerialAT.printf("version: %s\r\n", conf->version);
  SerialAT.printf("model: %s\r\n", conf->model);
  // SerialAT.printf("update_url: %s\r\n", conf->update_url);

  SerialAT.printf("wifi_ssid: %s\r\n", conf->wifi_ssid);
  SerialAT.printf("wifi_password: %s\r\n", conf->wifi_password);

  SerialAT.printf("mqtt_server: %s\r\n", conf->mqtt_server);
  SerialAT.printf("mqtt_port: %d\r\n", conf->mqtt_port);
  SerialAT.printf("mqtt_clientid: %s\r\n", conf->mqtt_clientid);
  SerialAT.printf("mqtt_pub: %s\r\n", conf->mqtt_pub);
  SerialAT.printf("mqtt_sub: %s\r\n", conf->mqtt_sub);
  SerialAT.printf("mqtt_sub_sys: %s\r\n", conf->mqtt_sub_sys);
  SerialAT.printf("mqtt_user: %s\r\n", conf->mqtt_user);
  SerialAT.printf("mqtt_password: %s\r\n", conf->mqtt_password);
}


void AtConfig::waitResponse(uint32_t timeout_ms) {
  unsigned long startMillis = millis();
  uint8_t len = 0;
  String recv = "";
  String value = "";
  do {
    while (SerialAT.available() > 0) {
      recv += char(SerialAT.read());
      len++;
    }
    if (len > 0) {
      if (recv.endsWith("\r\n")) {
        SerialAT.println(recv);
        status = ATCONFIG_CONF;
        if (recv.startsWith("AT+QUIT")) {
          status = ATCONFIG_QUIT;
          goto finish;
        }
        if (recv.startsWith("AT+CONF=")) {
          value = recv.substring(recv.indexOf("=") + 1, recv.length() - 2);
          write(ADDR_BASE_CONF, value);
          goto finish;
        }
        if (recv.startsWith("AT+CONF?")) {
          value = read(ADDR_BASE_CONF);
          SerialAT.println(value);
          goto finish;
        }
        SerialAT.println("AT ERROR");
        return;
      }
    }
  } while (millis()-startMillis < timeout_ms);
  return;

finish:
  SerialAT.println();
  SerialAT.println("DONE");
  return;
}

